package com.zhuang.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflecAccessMethod {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
			InstantiationException, InvocationTargetException {

		// 1. 得到Boss类对应的Class对象
		Class<?> bossCls = Class.forName("com.zhuang.reflection.Boss");
		// 2. 创建对象
		@SuppressWarnings("deprecation")
		Object o = bossCls.newInstance();
		// 3. 调用public的hi方法
		// Method hi = bossCls.getMethod("hi", String.class);//OK
		// 3.1 得到hi方法对象
		Method hi = bossCls.getDeclaredMethod("hi", String.class);// OK
		// 3.2 调用
		hi.invoke(o, "康小庄~");

		// 4. 调用private static 方法
		// 4.1 得到 say 方法对象
		Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
		// 4.2 因为say方法是private, 所以需要暴破，原理和前面讲的构造器和属性一样
		say.setAccessible(true);
		System.out.println(say.invoke(o, 100, "张三", '男'));
		// 4.3 因为say方法是static的，还可以这样调用 ，可以传入null
		System.out.println(say.invoke(null, 200, "李四", '女'));

		// 5. 在反射中，如果方法有返回值，统一返回Object , 但是他运行类型和方法定义的返回类型一致
		Object reVal = say.invoke(null, 300, "王五", '男');
		System.out.println("reVal 的运行类型=" + reVal.getClass());// String

		// 演示一个返回的案例
		Method m1 = bossCls.getDeclaredMethod("m1");
		Object reVal2 = m1.invoke(o);
		System.out.println("reVal2的运行类型=" + reVal2.getClass());// Monster

	}
}

class Monster {
}

class Boss {// 类
	public int age;
	@SuppressWarnings("unused")
	private static String name;

	public Boss() {// 构造器
	}

	public Monster m1() {
		return new Monster();
	}

	// 静态方法
	@SuppressWarnings("unused")
	private static String say(int n, String s, char c) {
		return n + " " + s + " " + c;
	}

	// 普通public方法
	public void hi(String s) {
		System.out.println("hi " + s);
	}
}
